package com.huaxin.device.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huaxin.device.dto.ResponseCode;
import com.huaxin.device.dto.ResponseResult;
import com.huaxin.device.dto.request.EquipmentModelCreateReqDTO;
import com.huaxin.device.dto.request.EquipmentModelPageListReqDTO;
import com.huaxin.device.dto.request.EquipmentModelUpdateReqDTO;
import com.huaxin.device.mapper.ElectricalEquipmentMapper;
import com.huaxin.device.mapper.EquipmentModelMapper;
import com.huaxin.device.mapping.EquipmentModelMapping;
import com.huaxin.device.models.EquipmentModel;
import com.huaxin.device.service.EquipmentModelService;
import com.huaxin.hxenum.enums.ActiveStatus;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.List;

import static org.springframework.util.StringUtils.hasText;

@Service
@RequiredArgsConstructor
public class EquipmentModelServiceImpl extends ServiceImpl<EquipmentModelMapper, EquipmentModel> implements EquipmentModelService {

    private final ApplicationContext applicationContext;
    private final EquipmentModelMapping mapping;
    private final EquipmentModelMapper mapper;
    private final ElectricalEquipmentMapper electricalEquipmentMapper;

    @Override
    public ResponseResult<EquipmentModel> create(EquipmentModelCreateReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        // 校验 modelCode + orgId 是否已存在
        if (existsByFields(EquipmentModel::getModelCode, in.getModelCode(), in.getOrgId(), null)) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "型号编码已存在", null);
        }
        // 校验 modelName + orgId 是否已存在
        if (existsByFields(EquipmentModel::getModelName, in.getModelName(), in.getOrgId(), null)) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "型号名称已存在", null);
        }

        EquipmentModel entity = mapping.toEntity(in);
        entity.setStatus(ActiveStatus.ACTIVE); // 默认启用

        if (!save(entity)) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "创建失败，请稍后再试", null);
        }

        return ResponseResult.ok(entity);
    }

    @Override
    public EquipmentModel getByModelId(String id) {
        if (!hasText(id)) {
            throw new IllegalArgumentException("ID不能为空");
        }
        EquipmentModel entity = getById(id);
        if (entity == null) {
            throw new IllegalArgumentException("设备型号不存在");
        }
        return entity;
    }

    @Override
    public ResponseResult<String> update(EquipmentModelUpdateReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        EquipmentModel entity = getByModelId(in.getId());

        // 校验 modelCode + orgId 是否已存在（不包含当前ID）
        if (existsByFields(EquipmentModel::getModelCode, in.getModelCode(), in.getOrgId(), in.getId())) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "型号编码已存在", null);
        }
        // 校验 modelName + orgId 是否已存在（不包含当前ID）
        if (existsByFields(EquipmentModel::getModelName, in.getModelName(), in.getOrgId(), in.getId())) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "型号名称已存在", null);
        }

        mapping.updateEntity(in, entity);
        if (!updateById(entity)) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "更新失败，请稍后再试", null);
        }

        return ResponseResult.ok("更新成功");
    }

    @Override
    public ResponseResult<String> delete(String id) {
        EquipmentModel entity = getByModelId(id);

        // 判断是否存在关联的设备
        if (electricalEquipmentMapper.existsByModelId(id)) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "请先解除关联的设备", null);
        }

        boolean removed = this.applicationContext.getBean(EquipmentModelService.class).removeById(id);
        if (!removed) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "删除失败，请稍后重试", null);
        }

        return ResponseResult.ok("删除成功");
    }

    @Override
    public ResponseResult<String> active(String id) {
        return toggleStatus(id, ActiveStatus.ACTIVE, "启用");
    }

    @Override
    public ResponseResult<String> inactive(String id) {
        return toggleStatus(id, ActiveStatus.INACTIVE, "禁用");
    }

    private ResponseResult<String> toggleStatus(String id, ActiveStatus status, String action) {
        EquipmentModel entity = getByModelId(id);

        entity.setStatus(status);
        if (!updateById(entity)) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, action + "失败，请稍后再试", null);
        }

        return ResponseResult.ok(action + "成功");
    }

    @Override
    public ResponseResult<IPage<EquipmentModel>> pageQuery(EquipmentModelPageListReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        IPage<EquipmentModel> page = new Page<>(in.getPageNum(), in.getPageSize());
        LambdaQueryWrapper<EquipmentModel> wrapper = new LambdaQueryWrapper<>();

        if (hasText(in.getModelCode())) {
            wrapper.like(EquipmentModel::getModelCode, in.getModelCode());
        }
        if (hasText(in.getModelName())) {
            wrapper.like(EquipmentModel::getModelName, in.getModelName());
        }
        if (hasText(in.getManufacturer())) {
            wrapper.like(EquipmentModel::getManufacturer, in.getManufacturer());
        }
        if (hasText(in.getStatus())) {
            wrapper.eq(EquipmentModel::getStatus, in.getStatus());
        }
        if (hasText(in.getOrgId())) {
            wrapper.eq(EquipmentModel::getOrgId, in.getOrgId());
        }
        if (hasText(in.getKeyword())) {
            wrapper.and(w -> w.like(EquipmentModel::getModelCode, in.getKeyword())
                    .or().like(EquipmentModel::getModelName, in.getKeyword())
                    .or().like(EquipmentModel::getDescription, in.getKeyword()));
        }

        wrapper.orderByDesc(EquipmentModel::getCreatedAt);
        IPage<EquipmentModel> resultPage = page(page, wrapper);
        return ResponseResult.ok(resultPage);
    }

    @Override
    public List<EquipmentModel> getByCategoryId(String categoryId) {
        LambdaQueryWrapper<EquipmentModel> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentModel::getCategoryId, categoryId)
                .eq(EquipmentModel::getStatus, "ACTIVE");
        return list(wrapper);
    }

    /**
     * 检查多个字段值组合是否已存在（排除当前ID）
     *
     * @param fieldGetter 字段Getter
     * @param fieldValue  字段值
     * @param orgId       组织ID
     * @param excludeId   要排除的ID（可为null）
     * @return 是否存在匹配记录
     */
    private boolean existsByFields(
            SFunction<EquipmentModel, ?> fieldGetter,
            Object fieldValue,
            String orgId,
            String excludeId) {

        if (fieldGetter == null) return false;

        LambdaQueryWrapper<EquipmentModel> wrapper = new LambdaQueryWrapper<>();

        if (fieldValue == null ||
                (fieldValue instanceof CharSequence cs && cs.toString().trim().isEmpty())) {
            wrapper.and(wrapper1 -> wrapper1
                    .isNull(fieldGetter)
                    .or().eq(fieldGetter, "")
            );
        } else {
            wrapper.eq(fieldGetter, fieldValue.toString().trim());
        }

        if (orgId == null || orgId.trim().isEmpty()) {
            wrapper.and(wrapper1 -> wrapper1
                    .isNull(EquipmentModel::getOrgId)
                    .or().eq(EquipmentModel::getOrgId, "")
            );
        } else {
            wrapper.eq(EquipmentModel::getOrgId, orgId.trim());
        }

        if (excludeId != null && !excludeId.trim().isEmpty()) {
            wrapper.ne(EquipmentModel::getId, excludeId.trim());
        }

        return this.count(wrapper) > 0;
    }
}